home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 07 - Mechanics - Environment / HexGridPlus / HexGrid.c next >
C/C++ Source or Header  |  1995-06-09  |  6KB  |  268 lines

  1. // HexGrid
  2.  
  3.  
  4. /*Size of the array*/
  5. #define    kArraySizeH    10
  6. #define    kArraySizeV    8
  7.  
  8.     
  9. /* Pictures*/
  10.     PicHandle hexTile, altTile, thirdTile;
  11.  
  12. /* Define constants that match our hexes */
  13. #define    kHorizontalSpacing    32
  14. #define    kVerticalSpacing    26
  15.  
  16.  
  17. /*HexToP: Convert grid coordinates to screen coordinates*/
  18.  
  19. Point HexToP(Point theHex, Point offset)
  20. {        
  21.     Point    returnValue;
  22.  
  23.     returnValue.v = kVerticalSpacing * theHex.v;
  24.     if ( (theHex.v & 1) == 0 )
  25.         returnValue.h = kHorizontalSpacing * theHex.h;
  26.     else
  27.         returnValue.h = kHorizontalSpacing * theHex.h + kHorizontalSpacing / 2;
  28.     return returnValue;
  29. }; /*HexToP*/
  30.  
  31.  
  32. /*AddToPoint: Offset a point by h,v*/
  33.  
  34. Point AddToPoint(Point p, short h, short v)
  35. {
  36.     Point    returnValue;
  37.  
  38.     returnValue.h = p.h + h;
  39.     returnValue.v = p.v + v;
  40.  
  41.     return returnValue;
  42. };
  43.  
  44.  
  45. /*MakePoint: Like SetPt but a function*/
  46.  
  47. Point MakePoint(short h, short v)
  48. {
  49.     Point    returnValue;
  50.  
  51.     returnValue.h = h;
  52.     returnValue.v = v;
  53.  
  54.     return returnValue;
  55. };
  56.  
  57.  
  58. /*GetNeighbor: Get a specified neighbor hex to a hex*/
  59.  
  60. Point GetNeighbor(Point source, short direction)
  61. {
  62.     Point    returnValue;
  63.  
  64. /*Direction 0 is to the right, then clockwise*/
  65.     if ( (source.v & 1) == 0 )
  66.         switch ( direction )
  67.         {
  68.             case 0: 
  69.                 returnValue = MakePoint(source.h + 1, source.v); break;
  70.             case 1: 
  71.                 returnValue = MakePoint(source.h, source.v + 1); break;
  72.             case 2: 
  73.                 returnValue = MakePoint(source.h - 1, source.v + 1); break;
  74.             case 3: 
  75.                 returnValue = MakePoint(source.h - 1, source.v); break;
  76.             case 4: 
  77.                 returnValue = MakePoint(source.h - 1, source.v - 1); break;
  78.             case 5: 
  79.                 returnValue = MakePoint(source.h, source.v - 1); break;
  80.             default:
  81.                 SysBeep(1);
  82.         }/*case*/
  83.         else
  84.         switch ( direction )
  85.         {
  86.             case 0: 
  87.                 returnValue = MakePoint(source.h + 1, source.v); break;
  88.             case 1: 
  89.                 returnValue = MakePoint(source.h + 1, source.v + 1); break;
  90.             case 2: 
  91.                 returnValue = MakePoint(source.h, source.v + 1); break;
  92.             case 3: 
  93.                 returnValue = MakePoint(source.h - 1, source.v); break;
  94.             case 4: 
  95.                 returnValue = MakePoint(source.h, source.v - 1); break;
  96.             case 5: 
  97.                 returnValue = MakePoint(source.h + 1, source.v - 1); break;
  98.             default:
  99.                 SysBeep(1);
  100.         };/*case*/
  101.     return returnValue;
  102. }; /*GetNeighbor*/
  103.  
  104.  
  105. /*Dist: Calculate the squared distance between two points*/
  106.  
  107. long Dist(Point p1, Point p2)
  108. {
  109.     return (p1.h - p2.h) * (p1.h - p2.h) + (p1.v - p2.v) * (p1.v - p2.v);
  110. };
  111.  
  112.  
  113. /*PToHex: For a point in screen coordinates, find the hex it is located in*/
  114.  
  115. Point PToHex(Point thePoint, Point offset)
  116. {
  117.     Point theHex;
  118.     Point p1, p2, p3;
  119.     Point h1, h2, h3;
  120.     long d1, d2, d3; /*integer?*/
  121.     Rect junkr; /*debug*/
  122.     Point tempPoint;
  123.  
  124. /*Find the hex in which "top rectangle" thePoint is located - not necessarily inside the hex*/
  125.     theHex.v = (thePoint.v - offset.v) / kVerticalSpacing;
  126.     if ( (theHex.v & 1) == 0 )
  127.         theHex.h = (thePoint.h - offset.h) / kHorizontalSpacing;
  128.     else
  129.         theHex.h = (thePoint.h - kHorizontalSpacing / 2 - offset.h) / kHorizontalSpacing;
  130.  
  131. /*Find the three hexes that are closest to thePoint*/
  132.     h1 = theHex;                            /*The lower hex*/
  133.     h2 = GetNeighbor(theHex, 4);        /*The upper-left hex*/
  134.     h3 = GetNeighbor(theHex, 5);        /*The upper-right hex*/
  135.  
  136. /*Get the center of each hex*/
  137.     p1 = AddToPoint(HexToP(h1, offset), kHorizontalSpacing / 2, kVerticalSpacing / 2);
  138.     p2 = AddToPoint(HexToP(h2, offset), kHorizontalSpacing / 2, kVerticalSpacing / 2);
  139.     p3 = AddToPoint(HexToP(h3, offset), kHorizontalSpacing / 2, kVerticalSpacing / 2);
  140.  
  141. /* The following plot the centers and the rectangle in which the point is located */
  142. /* It is here for debugging and demo purposes - remove if you use this in a real program! */
  143.     MoveTo(p1.h, p1.v);
  144.     Line(0, 0);
  145.     MoveTo(p2.h, p2.v);
  146.     Line(0, 0);
  147.     MoveTo(p3.h, p3.v);
  148.     Line(0, 0);
  149.     tempPoint = HexToP(theHex, offset);
  150.     junkr.left = tempPoint.h;
  151.     junkr.top = tempPoint.v;
  152.     tempPoint = AddToPoint(HexToP(theHex, offset), kHorizontalSpacing, kVerticalSpacing);
  153.     junkr.right = tempPoint.h;
  154.     junkr.bottom = tempPoint.v;
  155.     FrameRect(&junkr);
  156.  
  157. /*Calculate the (squared) distance from thePoint to each hex center*/
  158.     d1 = Dist(p1, thePoint);
  159.     d2 = Dist(p2, thePoint);
  160.     d3 = Dist(p3, thePoint);
  161. /*Pick the nearest hex!*/
  162.     if ( d1 < d2 )
  163.         if ( d3 < d1 ) /*not d2*/
  164.     /*d3*/
  165.             return h3;
  166.         else
  167.     /*d1*/
  168.             return h1;
  169.     else if ( d2 < d3 ) /*not d1*/
  170.     /*d2*/
  171.         return h2;
  172.     else
  173.     /*d3*/
  174.         return h3;
  175.  
  176. }; /*PToHex*/
  177.  
  178.  
  179.  
  180. /* Draw a tile */
  181.  
  182. void DrawHexTile(short h, short v, PicHandle hexTile)
  183. {
  184.     Rect tileRectangle;
  185.  
  186. /* Use the picture frame */
  187.     tileRectangle = hexTile[0]->picFrame;
  188. /* Move it to 0,0 */
  189.     OffsetRect(&tileRectangle, -tileRectangle.left, -tileRectangle.top);
  190. /* Offset to the proper position */
  191. /* For every other line, offset a bit extra */
  192.     if ( (v & 1) == 0 )
  193.         OffsetRect(&tileRectangle, kHorizontalSpacing * h, kVerticalSpacing * v);
  194.     else
  195.         OffsetRect(&tileRectangle, kHorizontalSpacing * h + kHorizontalSpacing / 2, kVerticalSpacing * v);
  196. /* Draw it */
  197.     DrawPicture(hexTile, &tileRectangle);
  198. }; /*DrawHexTile*/
  199.  
  200.  
  201. /* Standard inits */
  202.  
  203. void InitToolbox()
  204. {
  205.     InitGraf(&qd.thePort);
  206.     InitFonts ();
  207.     FlushEvents(everyEvent, 0);
  208.     InitWindows ();
  209.     InitMenus ();
  210.     TEInit ();
  211.     InitDialogs(nil);
  212.     InitCursor ();
  213. };
  214.  
  215. /****************** Main program ******************/
  216.  
  217. void main(void)
  218. {
  219.     WindowPtr myWindow;
  220.     Rect windowRectangle;
  221.     short h, v;
  222.     Point where; /*debug*/
  223.     short direction;
  224.     Point neighbor;
  225.  
  226.     InitToolbox();
  227.  
  228. /*Set up the window*/
  229.     SetRect(&windowRectangle, 50, 50, 50 + kArraySizeH * kHorizontalSpacing + kHorizontalSpacing / 2, 50 + kArraySizeV * kVerticalSpacing + kVerticalSpacing / 3);
  230.     myWindow = NewCWindow(nil, &windowRectangle, "\pHex grid demo", true, 0, (WindowPtr)-1L, false, 0);
  231.     SetPort(myWindow);
  232.  
  233. /*Load the picture*/
  234.     hexTile = GetPicture(128);            /*PICT resource #128.*/
  235.     altTile = GetPicture(129);
  236.     thirdTile = GetPicture(130);
  237.  
  238. /*Draw all tiles!*/
  239.     for ( h = 0 ; h <= kArraySizeH - 1 ; h++)
  240.         for ( v = 0 ; v <= kArraySizeV - 1 ; v++)
  241.             DrawHexTile(h, v, hexTile);
  242.  
  243.     while ( ! Button () )
  244.         ;
  245.  
  246. /*Demonstrate PToHex by drawing the hex in which the mouse is*/
  247.  
  248.     GetMouse(&where);
  249.     where = PToHex(where, MakePoint(0, 0));
  250.  
  251.     while ( Button () )
  252.         ;
  253.  
  254.     DrawHexTile(where.h, where.v, altTile);
  255.  
  256. /*Demonstrate GetNeighbor by drawing the neighbors as well*/
  257.  
  258.     for ( direction = 0 ; direction <= 5 ; direction++)
  259.         {
  260.             neighbor = GetNeighbor(where, direction);
  261.             DrawHexTile(neighbor.h, neighbor.v, thirdTile);
  262.         };
  263.  
  264.     while ( ! Button () )
  265.         ;
  266.  
  267. } /*TextGrid*/
  268.